#ifndef C_GENERATOR_H
#define C_GENERATOR_H

#include "code_generator.h"

#include <fstream>
#include <map>

namespace pp
{
    class CGenerator : public CodeGenerator
    {
    private:
        std::map<std::string, std::string> m_oConstMap;         // 常量所在类
        std::string m_sDefaultArraySize;                        // 数组字段默认最大数量
        std::string m_sDefaultStringSize;                       // 字符串字段默认最大数量
        std::string m_sFieldEncodeSize;                         // 字段编码默认最大长度
        std::string m_sJsonType;                                // 支持的json类型
    public:
        CGenerator(const std::string& srcdir, const std::string& outdir) : CodeGenerator(srcdir, outdir) {}
    public:
        // 重置数据
        virtual void Reset(const std::string& srcfile); // srcfile是pp定义文件名
        // 处理pp文件中的import定义
        virtual void HandleImport(const std::string& imports);
        // 处理pp文件中的option定义，忽略不支持的option。比如option go_package是一个option
        virtual void HandleOption(const std::string& name, const std::string& value);
        // 处理pp文件中的常量定义
        virtual void HandleConst(const std::shared_ptr<FieldInfo>& fieldInfo);
        // 处理pp文件中的enum定义
        virtual void HandleEnum(const std::shared_ptr<StructInfo>& structInfo);
        // 处理pp文件中的message定义
        virtual void HandleStruct(const std::shared_ptr<StructInfo>& structInfo);
        // 生成文件
        virtual void Generate();
    protected:
        // 生成头文件内容
        void GenerateHeadFile(const std::string& outdir, const std::string& filename);
        // 头文件宏定义
        void GenerateHeadMacro(std::ofstream& ofs, const std::string& filename);
        // 头文件include
        void GenerateHeadImport(std::ofstream& ofs);
        // 头文件类声明
        void GenerateHeadClassDeclare(std::ofstream& ofs);
        // 头文件宏定义
        void GenerateHeadConst(std::ofstream& ofs);
        // 头文件枚举定义
        void GenerateHeadEnum(std::ofstream& ofs);
        // 头文件枚举值
        void GenerateHeadEnumValues(std::ofstream& ofs, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // 头文件消息类定义
        void GenerateHeadClass(std::ofstream& ofs);
        // 头文件消息类成员定义
        void GenerateHeadClassAttributes(std::ofstream& ofs, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // 头文件消息函数
        void GenerateHeadFunction(std::ofstream& ofs);
        // 生成实现文件内容
        void GenerateCFile(const std::string& outdir, const std::string& filename);
        // CPP文件类实现函数
        void GenerateCppClass(std::ofstream& ofs);
        // CPP文件初始化函数
        void GenerateInitFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // CPP文件编码函数
        void GenerateEncodeFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // CPP文件解码函数
        void GenerateDecodeFunction(std::ofstream& ofs, const std::string& className, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // CPP文件ToJson函数
        void GenerateToJsonFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // CPP文件ToString函数
        void GenerateToStringFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
        // CPP文件FromJson函数
        void GenerateFromJsonFunction(std::ofstream& ofs, const std::string& className, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals);
    protected:
        // 功能函数
        std::string GetFileMacro(const std::string& filename);
        // 命名空间
        std::string GetNameSpace() const {return m_sPackage;}
        // 数组字段默认最大数量
        std::string GetDefaultArraySize() const {return m_sDefaultArraySize.empty() ? "128" : m_sDefaultArraySize;}
        // 字符串字段默认最大长度
        std::string GetDefaultStringSize() const {return m_sDefaultStringSize.empty() ? "256" : m_sDefaultStringSize;}
        // 子字段编码最大长度
        std::string GetFieldEncodeSize() const {return m_sFieldEncodeSize.empty() ? "2048" : m_sFieldEncodeSize;}
        // 命名空间产生的缩进
        std::string GetNameSpaceIndentation() {return "";}
        // 返回数据类型
        std::string GetClassType(const std::string& ftype);
        // 返回类成员定义
        std::string GetClassAttribute(const std::string& ftype, const std::string& subtype, const std::string& name,
            const std::string& arraySize);
        // 返回类成员名
        std::string GetClassAttributeName(const std::string& ftype, const std::string& subtype, const std::string& name);
        // 返回生成的文件名
        std::string GetHeadFile();
        // 获取常量配置
        const std::map<std::string, std::string>& GetConstMap() const {return m_oConstMap;}
        // 引入其他PP文件定义的常量、message(常量可以在tag，default，size等属性中使用)
        std::string GetImportValue(const std::string& constVal, bool bstring = false);
    };
};

#endif
